#ifndef FIFO_QUEUE_H
#define FIFO_QUEUE_H

#include <iostream>
#include <stdexcept>
#include <mutex>
#include <condition_variable>
#include <memory>  // 用于智能指针

template <typename T>
class FIFOQueue {
public:
	FIFOQueue(size_t capacity);          // 构造函数，传入队列大小
	~FIFOQueue();                        // 析构函数

	void push(std::unique_ptr<T> data);  // 入队操作，接受unique_ptr
	std::unique_ptr<T> pop();            // 出队操作，返回unique_ptr
	bool isEmpty() const;                // 判断队列是否为空
	bool isFull() const;                 // 判断队列是否已满
	size_t size() const;                 // 获取当前队列大小
	size_t capacity() const;             // 获取队列最大容量
	void clear();                        // 清空队列

private:
	std::unique_ptr<T>* buffer_;         // 存储数据的缓冲区，使用unique_ptr数组
	size_t head_;                        // 队列头指针
	size_t tail_;                        // 队列尾指针
	size_t size_;                        // 当前队列大小
	size_t capacity_;                    // 队列最大容量
	mutable std::mutex mtx_;             // 互斥锁
	std::condition_variable not_empty_;  // 条件变量，用于空队列时的等待
	std::condition_variable not_full_;   // 条件变量，用于满队列时的等待
};

// 构造函数
template <typename T>
FIFOQueue<T>::FIFOQueue(size_t capacity)
	: capacity_(capacity), head_(0), tail_(0), size_(0)
{
	buffer_ = new std::unique_ptr<T>[capacity_];  // 动态分配unique_ptr数组
}

// 析构函数
template <typename T>
FIFOQueue<T>::~FIFOQueue() {
	delete[] buffer_;  // 删除缓冲区
}

// 入队操作
template <typename T>
void FIFOQueue<T>::push(std::unique_ptr<T> data) {
	std::unique_lock<std::mutex> lock(mtx_);  // 使用 std::unique_lock

	// 如果队列满了，则等待
	while (isFull()) {
		not_full_.wait(lock);  // 队列已满，等待空间
	}

	buffer_[tail_] = std::move(data);  // 转移所有权
	tail_ = (tail_ + 1) % capacity_;
	size_++;

	// 通知消费者线程队列不为空
	not_empty_.notify_one();
}

// 出队操作
template <typename T>
std::unique_ptr<T> FIFOQueue<T>::pop() {
	std::unique_lock<std::mutex> lock(mtx_);  // 使用 std::unique_lock

	// 如果队列为空，则等待
	while (isEmpty()) {
		not_empty_.wait(lock);  // 队列为空，等待数据
	}

	std::unique_ptr<T> data = std::move(buffer_[head_]);  // 转移所有权
	head_ = (head_ + 1) % capacity_;
	size_--;

	// 通知生产者线程队列不满
	not_full_.notify_one();

	return data;  // 返回转移所有权的unique_ptr
}

// 判断队列是否为空
template <typename T>
bool FIFOQueue<T>::isEmpty() const {
	return size_ == 0;
}

// 判断队列是否已满
template <typename T>
bool FIFOQueue<T>::isFull() const {
	return size_ == capacity_;
}

// 获取当前队列大小
template <typename T>
size_t FIFOQueue<T>::size() const {
	return size_;
}

// 获取队列最大容量
template <typename T>
size_t FIFOQueue<T>::capacity() const {
	return capacity_;
}

// 清空队列
template <typename T>
void FIFOQueue<T>::clear() {
	std::lock_guard<std::mutex> lock(mtx_);
	head_ = 0;
	tail_ = 0;
	size_ = 0;
}

#endif // FIFO_QUEUE_H

/*
	 使用示例
#include <iostream>
#include <thread>
#include "FIFOQueue.h"

void producer(FIFOQueue<int>& queue) {
	for (int i = 0; i < 10; ++i) {
		queue.push(i);
		std::cout << "Produced: " << i << std::endl;
	}
}

void consumer(FIFOQueue<int>& queue) {
	for (int i = 0; i < 10; ++i) {
		int data = queue.pop();
		std::cout << "Consumed: " << data << std::endl;
	}
}

int main() {
	FIFOQueue<int> queue(5);  // 队列最大容量为 5

	std::thread t1(producer, std::ref(queue));  // 生产者线程
	std::thread t2(consumer, std::ref(queue));  // 消费者线程

	t1.join();
	t2.join();

	return 0;
}
*/